/*
* Description: 系统性能计数器数据抓取
*/

#ifndef PERF_COUNTER_H
#define PERF_COUNTER_H
#include <mutex>
#include <vector>
#include <string>
#include <map>
#include <winsock2.h>
#include <windows.h>
#include <Pdh.h>
#include <DXGI.h>

namespace PerfCommonData {
    const int FRESH_PERFCOUNTER_CYCLE = 5000;
    const int GPU_ADAPTERLUID_HIGHPART_POS = 3;
    const int GPU_ADAPTERLUID_LOWPART_POST = 4;
    const int MIN_GPU_ADAPTERLUID_POST = 5;
    const std::wstring MICROSOFT_DISPLAY_ADAPTER_DESCRIPTER = L"Microsoft";
    const int HEXADECIMAL_PLACEHOLDER_LENGTH = 8;
    const int PID_POS = 1;
    const int WINDOWS_SYSTEM_PROCESS_PID = 4;
};

struct PerfCounterHandler {
    HQUERY handleQuery = NULL;
    PDH_HCOUNTER phCounterMemoryCacheBytes = NULL;
    PDH_HCOUNTER phCounterIODataBytesPerSec = NULL;
    PDH_HCOUNTER phCounterGpuData = NULL;
    PDH_HCOUNTER phCounterAllGpuData = NULL;
    std::vector<PDH_HCOUNTER> vecCpuCorePerfCounter = {};
};

// 取进程的线程和句柄信息，用来统计总的线程和句柄信息
struct ProcessThreadAndHandleInfo {
    DWORD pid = 0;
    std::wstring processName = L"";
    DWORD threadNum = 0;
    DWORD handleNum = 0;
};

class PerfCounter {
public:
    PerfCounter();
    ~PerfCounter();
    static PerfCounter& GetInstance();
    bool Init();
    void Stop();
    void GetProcessThreadAndHandleInfo(
        unsigned long long &totalProcess, unsigned long long &totalThread, unsigned long long &totalHandle);
    std::vector<double> GetCpuPerfCounterData();
    double GetSystemGpuUsage();
    double GetIOSpeed();

private:
    int cpuCoreNum = 0;
    bool isInited = false;
    HQUERY handleQuery = NULL;
    PDH_HCOUNTER phCounterMemoryCacheBytes = NULL;
    PDH_HCOUNTER phCounterIODataBytesPerSec = NULL;
    PDH_HCOUNTER phCounterGpuData = NULL;
    PDH_HCOUNTER phCounterAllGpuData = NULL;
    std::vector<PDH_HCOUNTER> vecCpuCoreCounter = {};
    // pair<vendorId, deviceId>到 gpu使用率的映射
    std::map<std::pair<uint32_t, uint32_t>, double> mapDeviceGpuUsage = {};
    // LUID到pair<vendorId, deviceId> 的映射
    std::map<std::wstring, std::pair<uint32_t, uint32_t>> mapLuidToDevice = {};
    std::mutex mtx = {};
    int GetProcessorNum();
    void GetPerfCounterValue(PDH_HCOUNTER counter, double& counterValue);
    bool InitCpuCorePerfHandle(const HQUERY handleQuery, std::vector<PDH_HCOUNTER>& vecCpuCorePerfCounter);
    bool InitDisplayAdapter();
    double GetDisplayDeviceMaxGpuUsage(std::map<std::pair<uint32_t, uint32_t>, double>& inGpuInfo);
    bool InnerInitPerfCounter(PerfCounterHandler& handlerInfo);
    std::wstring GetLuidStringFromAdapterDesc(const DXGI_ADAPTER_DESC& inValue);
    void GetLuidToDeviceInfo(const std::vector<IDXGIAdapter* > vecAdapter);
    bool InitDeviceGpuUsage();
    bool GetLuidMapping();
    double TraversePdhGpuInfo(PDH_FMT_COUNTERVALUE_ITEM* couterValueitems, DWORD itemCount);
    void AutoCloseHandle(HANDLE handle);
    void SplitString(const std::wstring& srcValue, std::vector<std::wstring>& result, const std::wstring& subValue);
};
#endif // !PERF_COUNTER_MGR_H